package cn.jbooter.dubbo.autoconfigure.rpc.filter;

import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.extension.Activate;
import com.alibaba.dubbo.common.logger.Logger;
import com.alibaba.dubbo.common.logger.LoggerFactory;
import com.alibaba.dubbo.rpc.Filter;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcContext;
import com.alibaba.dubbo.rpc.RpcException;
import com.alibaba.dubbo.rpc.RpcResult;
import com.alibaba.dubbo.rpc.service.GenericService;

import cn.jbooter.coms.exceptions.BaseException;

/**
 * 自定义异常处理过滤器
 * 
 * 
 *
 */
@Activate(group = Constants.PROVIDER,order=1) //,order=1 ,after="exception"
public class ExceptionFilter implements Filter {

	private final Logger logger;

	public ExceptionFilter() {
		this(LoggerFactory.getLogger(ExceptionFilter.class));
	}

	public ExceptionFilter(Logger logger) {
		this.logger = logger;
	}

	@Override
	public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
		try {
			Result result = invoker.invoke(invocation);
			if (result.hasException() && GenericService.class != invoker.getInterface()) {
				try {
					Throwable exception = result.getException();
					//打印异常
					logger.error(exception);
					logger.info("------------------");
					exception.printStackTrace();
					// 如果是自定义异常就包装成jdk的exception
					if (exception instanceof BaseException) {
						return new RpcResult(new Exception(ExceptionUtils.TRANSFORM_EXCEPTION_MESSAGE, exception));
					}
					// 否则原样返回,留给dubbo自带的异常处理器处理
					return result;
				} catch (Throwable e) {
					logger.warn("Fail to ExceptionFilter when called by " + RpcContext.getContext().getRemoteHost()
							+ ". service: " + invoker.getInterface().getName() + ", method: "
							+ invocation.getMethodName() + ", exception: " + e.getClass().getName() + ": "
							+ e.getMessage(), e);
					return result;
				}
			}
			return result;
		} catch (RuntimeException e) {
			logger.error("Got unchecked and undeclared exception which called by "
					+ RpcContext.getContext().getRemoteHost() + ". service: " + invoker.getInterface().getName()
					+ ", method: " + invocation.getMethodName() + ", exception: " + e.getClass().getName() + ": "
					+ e.getMessage(), e);
			throw e;
		}
	}

}
